package site.nullable.recorder.ui.viewmodel

import android.app.Application
import android.content.ContentUris
import android.content.ContentValues
import android.content.Context
import android.media.MediaScannerConnection
import android.os.Build
import android.provider.MediaStore
import androidx.annotation.RequiresApi
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.application
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import site.nullable.recorder.data.model.Recording
import site.nullable.recorder.repository.RecordingRepository
import site.nullable.recorder.service.AudioPlayerService
import site.nullable.recorder.service.AudioRecorderService
import kotlinx.coroutines.launch
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

class RecordingViewModel(application: Application) : AndroidViewModel(application) {
    private val recordingRepository = RecordingRepository(application)
    private val audioRecorderService = AudioRecorderService(application)
    private val audioPlayerService = AudioPlayerService()

    private val _recordings = MutableStateFlow<List<Recording>>(emptyList())
    val recordings: StateFlow<List<Recording>> = _recordings.asStateFlow()

    private val _currentRecording = MutableLiveData<Recording?>()
    val currentRecording: LiveData<Recording?> = _currentRecording

    private val _isRecording = MutableStateFlow(false)
    val isRecording: StateFlow<Boolean> = _isRecording.asStateFlow()

    private val _latestRecording = MutableStateFlow<Recording?>(null)
    val latestRecording: StateFlow<Recording?> = _latestRecording.asStateFlow()

    private val _errorMessage = MutableLiveData<String?>()
    val errorMessage: LiveData<String?> = _errorMessage

    // 暴露播放状态流
    val playbackState: StateFlow<AudioPlayerService.PlaybackState>
        get() = audioPlayerService.playbackState

    // 暴露当前播放路径流
    val currentPlayingPathFlow: StateFlow<String?>
        get() = audioPlayerService.currentPlayingPathFlow

    init {
        loadRecordings()
    }

    fun loadRecordings() {
        viewModelScope.launch {
            _recordings.value = recordingRepository.getAllRecordings()
        }
    }

    @RequiresApi(Build.VERSION_CODES.O)
    fun startRecording() {
        viewModelScope.launch {
            val currentTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss"))
            val fileName = "recording_${currentTime}.m4a"
            val recording = recordingRepository.createRecordingFile(fileName)

            recording?.let {
                val fileDescriptor = recordingRepository.getOutputFileDescriptor(it)
                fileDescriptor?.let { fd ->
                    if (audioRecorderService.startRecording(it, fd)) {
                        _currentRecording.value = it
                        _isRecording.value = true
                        _errorMessage.value = null
                    } else {
                        _errorMessage.value = "无法开始录音"
                    }
                } ?: run {
                    _errorMessage.value = "无法创建录音文件"
                }
            } ?: run {
                _errorMessage.value = "无法创建录音文件"
            }
        }
    }

    fun stopRecording() {
        if (audioRecorderService.stopRecording()) {
            _currentRecording.value?.let { recording ->
                _latestRecording.value = recording

                updateFileState(
                    application,
                    recording = recording
                );
            }
            _isRecording.value = false
            _currentRecording.value = null
            _errorMessage.value = null

            MediaScannerConnection.scanFile(application,
                arrayOf(_latestRecording.value?.filePath),
                arrayOf("audio/m4a")
            ) { path, uri ->
                loadRecordings() // 刷新列表
            }

        } else {
            _errorMessage.value = "停止录音时出错"
        }
    }

    fun playRecording(recording: Recording) {
        if (audioPlayerService.playRecording(recording.filePath)) {
            _errorMessage.value = null
        } else {
            _errorMessage.value = "无法播放录音"
        }
    }

    fun stopPlaying() {
        audioPlayerService.stopPlaying()
    }

    fun pausePlaying() {
        audioPlayerService.pausePlaying()
    }

    fun resumePlaying() {
        if (!audioPlayerService.resumePlaying()) {
            _errorMessage.value = "无法恢复播放"
        }
    }

    fun isPlaying(recording: Recording): Boolean {
        return audioPlayerService.isPlaying(recording.filePath)
    }

    // 添加检查当前是否正在播放任何录音的方法
    fun isAnyRecordingPlaying(): Boolean {
        return audioPlayerService.isPlaying()
    }

    fun deleteRecording(recording: Recording) {
        viewModelScope.launch {
            if (recordingRepository.deleteRecording(recording)) {
                // 如果正在播放被删除的录音，停止播放
                if (audioPlayerService.getCurrentPlayingPath() == recording.filePath) {
                    audioPlayerService.stopPlaying()
                }
                loadRecordings()
                _errorMessage.value = null
            } else {
                _errorMessage.value = "无法删除录音文件"
            }
        }
    }

    fun getCurrentAmplitude(): Int {
        return audioRecorderService.getCurrentAmplitude()
    }

    fun clearErrorMessage() {
        _errorMessage.value = null
    }

    override fun onCleared() {
        super.onCleared()
        if (audioRecorderService.isRecording()) {
            audioRecorderService.stopRecording()
        }
        audioPlayerService.stopPlaying()
    }
}

// 更新文件状态
private fun updateFileState(context: Context, recording: Recording) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        val contentValues = ContentValues().apply {
            put(MediaStore.Audio.Media.IS_PENDING, 0)
        }
        val uri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, recording.id)

        context.contentResolver.update(uri, contentValues, null, null)
    }
}
